
package dovs.phases;

import dovs.*;
import dovs.analysis.*;
import dovs.node.*;
import static dovs.Main.program;
import static dovs.Util.*;

import java.util.*;

/** 
 * 	Compiler phase to build maps from names to
 *	AST nodes for all named entities in the program.
 */
public aspect Environments extends DepthFirstAdapter {
	/** The canonical name of the class or interface */
	public String PTypeDecl.canonical_name;

	/** The classes and interfaces in the program */
	public Map<String,PTypeDecl> AProgram.type_env 
		= new LinkedHashMap<String,PTypeDecl>();
	/** The fields in the class */
	public Map<String,AFieldDecl> PTypeDecl.field_env
		= new LinkedHashMap<String,AFieldDecl>();
	/** The methods in the class */
	public Map<String,Set<AMethodDecl>> PTypeDecl.method_env
		= new LinkedHashMap<String,Set<AMethodDecl>>();
	/** The locals and formals in the method */
	public Map<String,ALocalDecl> ABlock.local_env
		= new LinkedHashMap<String,ALocalDecl>();

	/**
	 * Look up a class or interface with the given name by searching first the
	 * program and then the classpath.
	 * 
	 * @param full_name
	 *            the fully qualified name of the class or interface to look
	 *            for.
	 */
	public static PTypeDecl lookupNamedType(String full_name) {
		if (program.type_env.containsKey(full_name)) {
			return program.type_env.get(full_name);
		} else {
			return ClassEnvironment.lookupNamedType(full_name);
		}
	}

	// /////////////////////////////////////////////////////////////////////////
	// ERROR MESSAGES
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * Reports the error that two fields in the same class have the same name.
	 * 
	 * @param node
	 *            one of the field declarations
	 */
	@SuppressWarnings("unused")
	private static void errorDuplicateField(AFieldDecl node) {
		Errors.error(
				ErrorType.DUPLICATE_FIELD, 
				node.getName(), 
				"The field '" + node.getName().getText() + 
				"' is already defined.",
				false
		);
	}

	/**
	 * Reports the error that two types with the same canonical name have been
	 * declared.
	 * 
	 * @param node
	 *            one of the type declarations
	 */
	@SuppressWarnings("unused")
	private static void errorDuplicateType(PTypeDecl node) {
		Errors.error(
				ErrorType.DUPLICATE_TYPE, 
				node.getName(), 
				"Duplicate type " + node.canonical_name,
				false
		);
	}

	/**
	 * Reports the error that two variables with overlapping scope have the same
	 * name.
	 * 
	 * @param node
	 *            one of the local declarations
	 */
	@SuppressWarnings("unused")
	private static void errorDuplicateVariable(ALocalDecl node) {
		Errors.error(
				ErrorType.DUPLICATE_VARIABLE, 
				node.getName(), 
				"The variable '" + node.getName() + 
				"' is already defined.",
				false
		);
	}

}
